package com.github.bitsapling.sapling.service.impl;

import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.anno.Cached;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.bitsapling.sapling.config.TrackerConfig;
import com.github.bitsapling.sapling.enums.AnnounceEventType;
import com.github.bitsapling.sapling.mapper.TransferHistoryMapper;
import com.github.bitsapling.sapling.entity.Torrent;
import com.github.bitsapling.sapling.entity.TransferHistory;
import com.github.bitsapling.sapling.entity.User;
import com.github.bitsapling.sapling.service.SettingService;
import com.github.bitsapling.sapling.service.TransferHistoryService;
import jakarta.annotation.Resource;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.List;


@Service
public class TransferHistoryServiceImpl implements TransferHistoryService {
    @Resource
    private TransferHistoryMapper transferHistoryMapper;

    @Resource
    private SettingService settingService;

    @Override
    public TransferHistory getTransferHistory(@NotNull User user, @NotNull Torrent torrent) {
        return transferHistoryMapper.selectOne(
                new QueryWrapper<TransferHistory>().eq("user_id", user.getId())
                .eq("torrent_id", torrent.getId())
        );
    }

    @Override
    public List<TransferHistory> getTransferHistory(@NotNull User user) {
        return transferHistoryMapper.selectList(
                new QueryWrapper<TransferHistory>().eq("user_id", user.getId()).orderByDesc("updated_at")
        );
    }

    @Override
    public List<TransferHistory> getTransferHistory(@NotNull Torrent torrent) {
        return transferHistoryMapper.selectList(
                new QueryWrapper<TransferHistory>().eq("torrent_id", torrent.getId()).orderByDesc("updated_at")
        );
    }

    @Override
    @NotNull
    @Cached(expire = 600, cacheType = CacheType.BOTH)
    public PeerStatus getPeerStatus(@NotNull Torrent torrent) {
        TrackerConfig config = settingService.get(TrackerConfig.getConfigKey(), TrackerConfig.class);
        List<TransferHistory> histories = getTransferHistory(torrent);
        int complete = 0;
        int incomplete = 0;
        int downloaders = 0;
        int downloaded = 0;
        for (TransferHistory history : histories) {
            if (isTransferActive(history, config)) {
                if (AnnounceEventType.PAUSED.name().equals(history.getLastEvent())) { // 部分做种
                    downloaders++;
                    continue;
                }
                if (history.getHaveCompleteHistory()) { // 曾经完成过下载
                    downloaded++;
                }
                if (history.getLeftByte() == 0) { // 下载报告已完成
                    complete++;
                } else { // 下载还未完成 (不和 haveCompleteHistory 合并，因为可以下载多次）
                    incomplete++;
                }
            } else {
                if (history.getLeftByte() == 0) { // 下载报告已完成
                    complete++;
                }
                if (history.getHaveCompleteHistory()) { // 曾经完成过下载
                    downloaded++;
                }
            }
        }
        return new PeerStatus(complete, incomplete, downloaded, downloaders);
    }

    private boolean isTransferActive(TransferHistory history, TrackerConfig config) {
        Timestamp timestamp = Timestamp.from(Instant.now().minus(config.getTorrentIntervalMax() + 15000, ChronoUnit.MILLIS));
        return history.getUpdatedAt().isAfter(timestamp.toLocalDateTime());
    }

    @Override
    public TransferHistory createOrUpdate(@NotNull TransferHistory transferHistory) {
        if (transferHistory.getId() == null) {
            return transferHistoryMapper.insert(transferHistory) > 0? transferHistory : null;
        }
        return transferHistoryMapper.updateById(transferHistory) > 0? transferHistory : null;
    }
}
